For my first two years at the Washington State Department of Agriculture (WSDA), I spent a lot of time wading in salmonid-bearing streams as an environmental technician. Eventually, I was ready to spend less time in the field and more in the office, so I applied for a data scientist position on the soil health team at WSDA.
Jadey Ryan in waders measuring streamflow in an agricultural ditch.
As part of the interview process, I had to automate custom soil health reports—one for each farmer. I spent days and nights frantically learning how to use R to automate clear, aesthetically pleasing, and informative reports. Parameterized reports with R Markdown turned out to be the solution, and my gravitas for efficiency, beautifully formatted work, and quick learning paid off, and I was hired!
Once we got the hang of parameterizing and automating the reports, it became quite addictive to find and integrate other amazing Quarto features! Here’s how parameterized reports with Quarto transformed our workflow and process.
A real-life application: automated custom soil health reports
Since 2020, we collected and analyzed over 1,000 soil samples to develop a baseline of soil health in Washington State as part of the State of the Soils Assessment. We created customized soil health reports for more than 300 participating farmers to help them access, understand, and translate their soil data into informed management decisions.
Parameterized reports with Quarto allowed us to automate the process of dynamically generating hundreds of customized reports in two formats: interactive HTML and printable PDF. Without the powerful capabilities of Quarto, we would not have had the staff capacity to create these comprehensive reports in both formats.
Watch the ✨ magic ✨ as more than 14 reports are automatically generated one after another from an R script. Notice the ETA of 17 minutes shown in the progress bar (a feature of purrr::pwalk()):
We also turned this Quarto project into an R package called soils, which you can learn about in this blog post or this webinar.
Now, let’s zoom out from our niche soil health report example and talk about how any data professionals can use Quarto to automate their analytics reports.
Analytics report automation with Quarto
Data professionals transform raw data into actionable insights, which are then communicated to decision-makers in reports. Variations of the report may be generated for alternative analyses, time periods, regions, or other groupings of the data.
There is a spectrum of ways to produce these report variations with varying levels of automation:
Fully manual: run the analysis one variation at a time in Excel, R, or Python, and then manually embed the tables and figures output into each report.
Mostly manual: use literate programming with Quarto to weave together the code and narrative into a separate Quarto document for each report variation.
Mostly automated: parameterize a Quarto document by defining and using computational parameters, and then generate each report variation by changing the parameters and rendering.
Fully automated: programmatically render all report variations at once by running an R or Bash/shell script to render the parameterized Quarto template with each of the defined parameters.2
If your current workflow is similar to the Fully manual or Mostly manual options above, consider how you might feel if asked to regenerate all the report variations after an update to the data. How much time and tedious labor would it take and how many potential copy/paste errors would arise?
Instead, imagine the Mostly automated or Fully automated options in which you update the data and re-render all reports from a parameterized Quarto template. Think of how much more time you could have to work on higher impact projects!
Are you convinced about the benefits of using Quarto for parameterized reporting yet? Keep reading to learn exactly how they work and how you can create them!
How Quarto parameterized reports work
Parameterized reports are similar to functions, where the Quarto template document (.qmd file) is the function, the parameter is the input, and the report variations are the output. You can have as few or as many parameters as you like.
Parameters can be character, integer, numeric, or logical variables. The custom soil health reports used two parameters: producer_id <chr> and year <int>. These parameters were used in the report headings as inline code, and in code chunks to filter the data and highlight only the farmer’s data. See what this looks like in the Define and access parameters section. For all the source code to generate the soil health reports, see the soils GitHub repository.
Parameterized reports function similarly to code functions. The Quarto template document (.qmd file) acts as the function, the parameter (params$year) is the input, and the report variations are the outputs. This figure illustrates how a single template, with different input parameters, produces reports for various years (2019, 2020, 2021, 2022, 2023) (Ryan et al. 2023).
How to create a parameterized report
Our roadmap
Setting and using parameters: Parameters are defined in the YAML header (Knitr) or parameters cell (Jupyter). They are accessed in the report content and code chunks.
Rendering one-at-a-time: Render reports one at a time by changing parameters manually or using command-line tools.
Rendering all at once: Automate the rendering of all report variations with a script.
Define and access parameters
Parameters are defined and accessed differently depending on whether you use the Knitr or Jupyter engine.
To render all report variations at once, write an R or Bash/shell script to render the parameterized Quarto template with each of the defined parameters.
Create a dataframe with three columns that match the quarto::quarto_render() function arguments: output_format, output_file, and execute_params.
Code
data <-expand.grid(year =c(2022, 2023),producer_id =c("ABC01", "ABC02", "XYZ01", "XYZ02"), stringsAsFactors =FALSE)df <- data |> dplyr::mutate(output_format ="html", # Output format (html, word, etc.)output_file =paste( # Output file name year, producer_id, "report.html",sep ="-" ),execute_params = purrr::map2( # Named list of parameters producer_id, year, \(producer_id, year) list(producer_id = producer_id, year = year) ) ) |> dplyr::select(-c(producer_id, year))df
output_format
output_file
execute_params
html
2022-ABC01-report.html
ABC01, 2022
html
2023-ABC01-report.html
ABC01, 2023
html
2022-ABC02-report.html
ABC02, 2022
html
2023-ABC02-report.html
ABC02, 2023
html
2022-XYZ01-report.html
XYZ01, 2022
html
2023-XYZ01-report.html
XYZ01, 2023
html
2022-XYZ02-report.html
XYZ02, 2022
html
2023-XYZ02-report.html
XYZ02, 2023
Use purrr::pwalk() to map over each row of the dataframe and render each report variation.
purrr::pwalk(.l = df, # Dataframe to map over.f = quarto::quarto_render, # Quarto render functioninput ="template.qmd", # Named arguments of .f.progress =TRUE# Optionally, show a progress bar)
I’m no expert in Bash or shell scriping and prefer R all around. However, Solomon Moon’s Posit blog post on Quarto reporting infrastructure has a section on parameterized reporting that includes demo code to render all report variations in a Bash/shell script.
End-to-end workflow
Creating parameterized reports with Quarto involves a systematic approach that ensures flexibility, efficiency, and reproducibility. To help you navigate this process, let’s walk through an end-to-end workflow that transforms your reporting process from manual to fully automated. This step-by-step guide takes you from drafting a basic report template to rendering all variations at once.
For a demonstration of the workflow with example Quarto files and code, follow along with one of my parameterized reporting workshops.
Create the report template without parameters (i.e., hard-code all variables)
Begin by drafting your report with fixed values. This allows you to focus on the content and structure without worrying about parameterization. Render your report to see how it looks, review it for accuracy and clarity, and make any necessary adjustments.
Set default parameters
Once you’re happy with the initial version, it’s time to introduce parameters. Define your parameters and set default values. In Knitr, this is done in the YAML header, whereas Jupyter uses a designated parameters cell.
Replace hard-coded values with parameters
Replace your hard-coded values with the corresponding parameter names. This transforms your static report into a flexible template in which the parameter names are placeholders to be replaced with the parameter values when the report is rendered.
Render the single report with the default parameters
Render the newly parameterized report. Review the output to ensure everything works as expected. Make any necessary adjustments to refine your report.
Check for missed hard-coded values
Change the default parameters, render, and check for any places you forgot to replace the hard-coded values with parameters.
Render extreme cases
To ensure robustness, test your report with extreme parameter values. This could mean rendering a report with minimal data, maximal data, or using the boundary values for your parameters. This step helps identify any formatting or presentation issues that might arise in edge cases
For example, I tested my edge cases by rendering reports for a farmer who had only one sample and a farmer who had ten samples. This helped me identify and correct awkward page breaks for reports with more than eight samples.
Use a script to render all variations of the report at once
Finally, when you’re confident that your report handles all scenarios gracefully, render all desired variations with an R or Bash/shell script.
Parameterized reports are magic! ✨
In conclusion, parameterized Quarto reports have transformed our workflow at WSDA, allowing us to automate and customize soil health reports efficiently. This shift from manual labor to streamlined, code-based analysis and reporting exemplifies the power of leveraging the right tools and processes. One of the joys of becoming a code-based analyst is the ability to build on previous work, ensuring each report isn’t a bespoke endeavor but part of a scalable and impactful system.
One of Jadey’s cats is sitting on her laptop with RStudio on the screen.
Parameterized reports took me from pulling leeches off my boots to pulling cats off my keyboard—transforming how we handle data and deliver insights.
Whether you’re in agriculture, finance, or any data-driven field, adopting Quarto for parameterized reporting can save time, reduce errors, and allow you to focus on higher-impact projects. Ready to transform your reporting process? Parameterize and automate your reports so you can have time for a cat nap. 🐱
Learn how you can parameterize reports and presentations with Quarto!
While this post talked only of parameterized reports, you can also parameterize presentations with Quarto. Jumping Rivers has a blog post demonstrating the process of defining parameters within a Quarto Reveal JS presentation.
Appendix: Parameters in R Markdown
The concept of parameterized reports may already be a familiar concept to R Markdown users. In fact, there is a very nice quality-of-life feature for R Markdown parameters not yet implemented for Quarto: .Rmd documents with parameters have a a Knit with Parameters GUI built with Shiny miniUI.
The current workaround is to build a web app to get the input, serialize to the YAML header, and then render, as described in this GitHub discussion. If a Parameters GUI for Quarto seems useful to you, upvote quarto-dev/quarto-r issue #132.
Why use Quarto instead of R Markdown?
If you don’t absolutely need the Parameters GUI, you may be wondering if you should use Quarto for parameterized reports instead of R Markdown. While R Markdown is not going away, Quarto is the next-generation that combines and expands upon the functionality of the R Markdown ecosystem into a single, consistent publishing system.
Moreover, Quarto is multi-language and multi-engine so not only R users benefit from parameterized reports, but also users of Python, Julia, and potentially new languages yet to be developed. Similarly, Quarto easily supports multiple report formats (PDF, Word, HTML, etc.) from a single document without the need for additional packages or unmanageable codebases.
To learn more about the differences between R Markdown and Quarto, read through the FAQ for R Markdown Users.
References
Ryan, Jadey, Molly McIlquham, Kwabena Sarpong, Leslie Michel, Teal Potter, Deirdre Griffin LaHue, and Dani Gelardi. 2023. “Parameterized Quarto Reports Improve Understanding of Soil Health.”Posit::conf(2023), September. https://jadeyryan.com/talks/2023-09-25_posit_parameterized-quarto.